<template>
<div class="player-wrapper">
    <div :class="['video-wrapper', {'video-wrapper-stretch': this.stretch_}]" :style="videoWrapperStyle">
        <div class="video-inner" :class="{ 'hide-controls': !controls }" style="position:absolute;top:0;bottom:0;left:0;right:0;background:#000;">
            <div class="qing-player"></div>
        </div>
        <div class="video-slot" v-show="showSlot">
            <slot></slot>
        </div>
        <span class="video-title" v-show="videoTitle && showSlot" :title="videoTitle">{{videoTitle}}</span>
    </div>
</div>
</template>

<script>
export default {
    name: 'qing-player',
    data() {
        return {
            player: null,
            timer: 0,
            fluentBtnCls: "qing-player-fluent-btn",
            stretchBtnCls: "qing-player-stretch-btn",
            snapFromOutside: false,
            snapForPoster: false,
            snapForReload: false,
            showSlot: false,
            fluent_: true,
            muted_: true,
            stretch_: false,
            poster_: "",
            avLoading: false,
            reloadCnt: 0,
            updateTimeAt: 0,
            flvMediaDataSource: {},
            flvConfig: {},
            resolutionName: {
                "sd": "标清",
                "hd": "高清",
                "fhd": "超清",
                "yh": "原画"
            },
            playbackRate_: 1,
            sub_: false,
            videoUrl_: "",
            slotEl: null,
            titleEl: null,
        }
    },
    props: {
        videoUrl: {
            type: String,
            default: ""
        },
        videoTitle: {
            type: String,
            default: ''
        },
        poster: {
            default: ""
        },
        autoplay: {
            type: Boolean,
            default: true
        },
        live: {
            type: Boolean,
            default: false
        },
        loading: {
            type: Boolean,
            default: false
        },
        currentTime: {
            type: Number,
            default: 0
        },
        timeout: {
            type: Number,
            default: 20
        },
        alt: {
            type: String,
            default: '无信号'
        },
        muted: {
            type: Boolean,
            default: true
        },
        aspect: {
            type: String,
            default: '16:9'
        },
        videoBufferSize: {
            type: Number,
            default: 200 * 1024
        },
        audioBufferSize: {
            type: Number,
            default: 128 * 1024
        },
        hlsErrorSeek: {
            type: Number,
            default: 5,
        },
        hlsTestMethod: {
            type: String,
            default: "HEAD",
        },
        reloadInterval: { // reconnect interval
            type: Number,
            default: 1000,
        },
        liveInterval: { // check live time update interval
            type: Number,
            default: 10000,
        },
        pauseWhenHidden: {
            type: Boolean,
            default: true
        },
        fluent: {
            type: Boolean,
            default: true
        },
        stretch: {
            type: Boolean,
            default: false
        },
        loop: {
            type: Boolean,
            default: false
        },
        controls: {
            type: Boolean,
            default: true
        },
        hideBigPlayButton: {
            type: Boolean,
            default: true
        },
        hideSnapshotButton: {
            type: Boolean,
            default: false
        },
        hideFullscreenButton: {
            type: Boolean,
            default: false
        },
        hideFluentButton: {
            type: Boolean,
            default: false
        },
        hideStretchButton: {
            type: Boolean,
            default: false
        },
        hidePicInPic: {
            type: Boolean,
            default: true
        },
        hideWaiting: {
            type: Boolean,
            default: true
        },
        showTime: {
            type: Boolean,
            default: () => {
                if (window.QingPlayer && (window.QingPlayer.browser.IS_IOS || window.QingPlayer.browser.IS_ANDROID)) {
                    return false;
                }
                return true;
            }
        },
        showCustomButton: {
            type: Boolean,
            default: true
        },
        debug: {
            type: Boolean,
            default: false
        },
        hasvideo: {
            type: Boolean,
            default: undefined
        },
        hasaudio: {
            type: Boolean,
            default: undefined
        },
        resolution: {
            type: String,
            default: ""
        },
        resolutiondefault: {
            type: String,
            default: "hd"
        },
        reconnect: {
            type: Boolean,
            default: false
        },
        playbackRates: {
            type: Array,
            default: () => {
                if (window.QingPlayer && (window.QingPlayer.browser.IS_IOS || window.QingPlayer.browser.IS_ANDROID)) {
                    return [];
                }
                return [0.5, 1, 2, 3];
            }
        },
        playbackRate: {
            type: Number,
            default: 1
        },
        cors: {
            type: Boolean,
            default: true
        },
        withCredentials: {
            type: Boolean,
            default: false
        },
        sub: {
            type: Boolean,
            default: false
        },
    },
    beforeDestroy() {
        this.destroyPlayer();
    },
    deactivated() {
        this.destroyPlayer();
    },
    watch: {
        videoUrl: function (val) {
            this.videoUrl_ = val;
            this.reload();
        },
        fluent: function (val) {
            this.fluent_ = val;
            this.reload();
        },
        muted: function (val) {
            this.muted_ = val;
            this.reload();
        },
        stretch: function (val) {
            this.stretch_ = val;
            this.reload();
        },
        poster: function (val) {
            this.poster_ = val;
        },
        loop: function (val) {
            this.reload();
        },
        currentTime: function (val) {
            this.player && this.player.currentTime(val);
        },
        sub: function (val) {
            this.sub_ = val;
        }
    },
    mounted() {
        this.muted_ = this.muted;
        this.fluent_ = this.fluent;
        this.stretch_ = this.stretch;
        this.poster_ = this.poster;
        this.playbackRate_ = this.playbackRate;
        this.sub_ = this.sub;
        this.videoUrl_ = this.videoUrl;
        this.initPlayer();
    },
    computed: {
        videoType() {
            let _type = "video/mp4";
            if (this.rtmp) {
                _type = "rtmp/mp4";
            } else if ((this.http || this.ws) && this.flv) {
                _type = "video/x-flv";
            } else if (this.m3u8) {
                _type = "application/x-mpegURL";
            }
            return _type;
        },
        videoWrapperStyle() {
            if (this.aspect == "100%" || this.aspect == "fullscreen") {
                return {
                    width: "100%",
                    height: "100%"
                }
            }
            var wh = this.aspect.split(':');
            var w = parseInt(wh[0]) || 16,
                h = parseInt(wh[1]) || 9;
            return {
                paddingBottom: h / w * 100 + '%',
                position: "relative",
                margin: "0 auto",
                overflow: "hidden"
            }
        },
        http() {
            return (this.src || "").indexOf("http") == 0;
        },
        ws() {
            return (this.src || "").indexOf("ws") == 0;
        },
        mp4() {
            return /\.mp4.*$/.test(this.src || "");
        },
        m3u8() {
            return /\.m3u8.*$/.test(this.src || "");
        },
        flv() {
            return /\.flv.*$/.test(this.src || "");
        },
        src() {
            if (!this.videoUrl_) {
                return "";
            }
            if (this.videoUrl_.indexOf("//") === 0) {
                return location.protocol + this.videoUrl_;
            }
            if (this.videoUrl_.indexOf("/") === 0) {
                return location.protocol + "//" + location.host + this.videoUrl_;
            }
            return this.videoUrl_;
        },
    },
    methods: {
        isMobile() {
            if (window.QingPlayer) {
                return window.QingPlayer.browser.IS_IOS || window.QingPlayer.browser.IS_ANDROID;
            }
            return false
        },
        reload() {
            this.reloadCnt++;
            if (this.debug) {
                console.log(`qingplayer reload[${this.reloadCnt}]`);
            }
            this.destroyPlayer();
            if (this.videoUrl_ != "") {
                this.initPlayer();
            }
        },
        destroyPlayer() {
            this.showSlot = false;
            if (this.timer) {
                clearInterval(this.timer);
                this.timer = 0;
            }
            var el = this.$el.querySelector(".qing-player");
            el && el.removeEventListener('fullscreenchange', this.onFullscreenChange);
            if (this.player) {
                this.player.destroy();
                this.player = null;
            }
            this.$emit("update:loading", false);
        },
        getCurrentTime() {
            if (this.player && typeof this.player.currentTime == 'function') {
                return this.player.currentTime();
            }
            return -1;
        },
        setCurrentTime(val) {
            if (this.player && typeof this.player.currentTime == 'function') {
                this.player.currentTime(val);
            }
        },
        play() {
            if (this.player) {
                this.player.play();
            }
        },
        pause() {
            if (this.player) {
                this.player.pause();
            }
        },
        paused() {
            if (this.player) {
                return this.player.paused();
            }
            return false;
        },
        setMuted(opt) {
            this.player && this.player.muted(!!opt);
        },
        getMuted() {
            if (this.player) {
                return this.player.muted()
            }
            return false;
        },
        setVolume(v) {
            this.player && this.player.volume(v);
        },
        getVolume() {
            if (this.player) {
                return this.player.volume();
            }
            return 0;
        },
        onFullscreenChange() {
            if (this.player) {
                this.$emit("fullscreen", this.player.isFullscreen());
            }
        },
        initPlayer(seekTime = 0) {
            if (!this.src) {
                return;
            }
            if (this.autoplay) {
                this.$emit("update:loading", true);
            }
            if ((this.http || this.ws) && (this.flv || this.m3u8)) {
                var el = this.$el.querySelector(".qing-player");
                this.player = new QingPlayer({
                    videoUrl: this.videoUrl_,
                    videoTitle: this.videoTitle,
                    poster: this.poster_,
                    autoplay: this.autoplay,
                    live: this.live,
                    loading: false,
                    aspect: "100%",
                    stretch: this.stretch_,
                    muted: this.muted_,
                    currentTime: this.currentTime,
                    controls: this.controls,
                    hideBigPlayButton: this.hideBigPlayButton,
                    cbFunc: (event, value) => {
                        this.$emit(event, value);
                    }
                }, el);
                el.addEventListener('fullscreenchange', this.onFullscreenChange);
                var wrapper = this.$el.querySelector(".video-wrapper");
                if (this.player && wrapper) {
                    if (this.slotEl) {
                        this.player.addElement(this.slotEl);
                    } else {
                        this.slotEl = wrapper.querySelector(".video-slot");
                        wrapper.removeChild(this.slotEl);
                        this.player.addElement(this.slotEl);
                    }
                    if (this.titleEl) {
                        this.player.addElement(this.titleEl);
                    } else {
                        this.titleEl = wrapper.querySelector(".video-title");
                        wrapper.removeChild(this.titleEl);
                        this.player.addElement(this.titleEl);
                    }
                }
                this.showSlot = true;
                this.player.play();
                if (this.autoplay) {
                    this.timer = setTimeout(() => {
                        this.checkLoaded(0);
                    }, 50)
                }
            } else {
                this.$emit("message", {
                    type: "error",
                    message: "不支持的播放类型"
                });
            }
        },
        checkLoaded(sum) {
            if (this.player && this.getCurrentTime() > 0) {
                this.$emit("update:loading", false);
            } else if (sum <= 300) {
                this.timer = setTimeout(() => {
                    this.checkLoaded(sum + 1);
                }, 50)
            }
        }
    }
}
</script>


<style lang="less">
.video-wrapper {
    .hide-controls {
        .qplayer-time-box {
            display: none !important;
        }
    }
}
</style>

<style lang="less" scoped>
.video-wrapper {
    .show-time .video-js .vjs-time-control:not(.vjs-remaining-time) {
        padding-left: 0.5em;
        padding-right: 0;
        min-width: 0;
        display: block;
    }

    .video-js .vjs-remaining-time {
        display: none;
    }

    .live .vjs-progress-control {
        visibility: hidden;
    }

    .live .vjs-remaining-time {
        display: none;
    }

    .live .vjs-time-control {
        display: none;
    }

    .av-loading .vjs-big-play-button {
        display: none;
    }

    .hide-waiting {
        .vjs-waiting .vjs-loading-spinner {
            display: none !important;
        }

        .vjs-seeking .vjs-loading-spinner {
            display: none !important;
        }
    }

    .hide-controls {
        .vjs-control-bar {
            display: none !important;
        }
    }

    .hide-big-play-button {
        .vjs-big-play-button {
            display: none !important;
        }
    }

    .hide-snapshot-button {
        .vjs-snapshot-control {
            display: none !important;
        }
    }

    .hide-fullscreen-button {
        .vjs-fullscreen-control {
            display: none !important;
        }
    }

    .hide-fluent-button {
        .live-player-fluent-btn {
            display: none !important;
        }
    }

    .hide-stretch-button {
        .live-player-stretch-btn {
            display: none !important;
        }
    }

    .hide-pic-in-pic {
        .video-js .vjs-picture-in-picture-control {
            display: none !important;
        }
    }

    .alt {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        vertical-align: middle;
        background-repeat: no-repeat;
        background-position: 50% 50%;
        background-size: contain;
        background-color: black;
        color: white;
        text-align: center;

        &>table {
            width: 100%;
            height: 100%;

            tr>td {
                vertical-align: middle;
            }
        }
    }

    .video-js {
        .video-slot {
            font-size: 14px;
        }

        .video-title {
            font-size: 14px;
            position: absolute;
            top: 5px;
            right: 5px;
            color: white;
            background-color: fade(gray, 50%);
            border-radius: 2px;
            padding: 5px;
            max-width: 120px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }
    }

    // .video-js .vjs-tech {
    //     pointer-events: none;
    // }

    .video-js .vjs-control-bar {
        .vjs-button {
            cursor: pointer;
            outline: none;
        }

        .vjs-icon-spinner:before {
            font-size: 1.4em;
            line-height: 1.87;
        }
    }

    .vjs-error-display {
        display: none;
    }

    .video-js .vjs-time-control {
        font-size: 1.035em;
        line-height: 2.93em;
    }

    .vjs-resolution-button {
        color: #ccc;
        font-family: VideoJS;
    }

    .vjs-resolution-button .vjs-resolution-button-staticlabel:before {
        content: '\f110';
        font-size: 1.8em;
        line-height: 1.7em;
    }

    .vjs-resolution-button .vjs-resolution-button-label {
        width: 100%;
        height: 0.6em;
        display: block !important;
    }

    .vjs-resolution-button .vjs-resolution-button-label-ie {
        width: 100%;
        height: 0.4em;
        display: block !important;
    }

    .vjs-resolution-button ul.vjs-menu-content {
        width: 4em !important;
    }

    .vjs-resolution-button .vjs-menu {
        left: 0;
    }

    .vjs-resolution-button .vjs-menu li {
        text-transform: none;
        font-size: 1em;
        line-height: 1.5em;
        font-family: Arial, Helvetica, sans-serif;
    }

    .vjs-audio-button {
        display: none !important;
    }

    // .vjs-picture-in-picture-control {
    //     display: none;
    // }

    // 修复在某些情况下(特别是页面缩放后), 控制栏图标在水平方向上不对齐的问题(图标或大或小, 或高或低)
    .video-js .vjs-big-play-button .vjs-icon-placeholder:before,
    .vjs-button>.vjs-icon-placeholder:before {
        position: relative !important;
    }

    // 修复回放进度条上的小圆点, 在某些情况下位置偏高
    .video-js .vjs-play-progress:before {
        top: -0.33em !important;
    }

    // 去 shadow
    .video-js .vjs-control:focus:before,
    .video-js .vjs-control:hover:before,
    .video-js .vjs-control:focus {
        text-shadow: none !important;
    }

    // css only for chrome
    @media screen and (-webkit-min-device-pixel-ratio:0) {
        .video-js .vjs-control-bar {
            font-size: 14px;
        }

        .video-js .vjs-slider-vertical .vjs-volume-level:before {
            left: -0.33em !important;
        }
    }

    &.video-wrapper-stretch {
        .alt {
            background-size: 100% 100%;
        }

        .video-js .vjs-poster {
            background-size: 100% 100%;
        }
    }
}
</style>
